<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>双向绑定任务二</title>
</head>
<body>
<script>
    let _obj = {},
        family = {},
//        观察者构造函数，将对应的属性绑定在新创建的对象上
        Observer = function (obj, key) {
            if (!key) {
                let that = this;
                that.data = {};
                walk(obj, that.data)
            } else {
                let that = this;
                delete that[key];
                this[key] = {};
                walk(obj, that[key]);
            }
        };
    //    $watch用来监听对应的属性
    Observer.prototype.$watch = function (key, fun) {
        let _fun;
        if (fun) {
            _fun = fun;
        }
        _obj[key] = _fun;
    };
    //    walk用来遍历属性赋值
    function walk(obj, data) {
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (typeof obj[key] !== "object") {
                    let _value = obj[key];
                    Object.defineProperty(data, key, {
                        get: function () {
                            console.log(`你访问了${key}`);
                            return _value;
                        },
                        set: function (value) {
                            if (value !== null && typeof value === "object") {
                                delete family[key];
                                for (let member in value) {
                                    if (value.hasOwnProperty(member)) {
                                        family[member] = {"parent": key};
                                    }
                                }
                                Observer.call(data, value, key);
                            }
                            else {
                                _value=value;
                                console.log(`你设置了${key},新的值为${_value}`);
                                _obj[key] && _obj[key]();
                                let method;
                                while (family[key] && (method = family[key].parent)) {
                                    _obj[family[key].parent] && _obj[family[key].parent]();
                                    key = family[key].parent;
                                }
                            }
                        },
                        configurable: true
                    });
                } else {
                    data[key] = {};
                    walk(obj[key], data[key]);
                }
            }
        }
    }
    let app1 = new Observer({
        name: 'Edward',
        age: 25
    });
    app1.data.name = {
        lastName: 'Naiqian',
        firstName: 'Ren'
    };
</script>
</body>
</html>